package net.alteiar.algorithms;

import net.alteiar.algorithms.builder.InstanceBuilder;
import net.alteiar.images.BasicImage;
import net.alteiar.images.metadata.ImageInfo;
import weka.clusterers.Clusterer;
import weka.clusterers.SimpleKMeans;
import weka.core.Attribute;
import weka.core.EuclideanDistance;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;

public class ClusteringUtils {

	public static ImageInfo buildImageInfo(BasicImage img, int squareSize) {
		ImageInfo info = new ImageInfo(img, squareSize);

		for (int x = 0; x < info.getWidthSquare(); ++x) {
			for (int y = 0; y < info.getHeightSquare(); ++y) {
				info.setValue(x, y, img.getImage().getRGB(x, y));
			}
		}

		return info;
	}

	public static ImageInfo createKMeansGraphics(ImageInfo img,
			InstanceBuilder builder, int numCluster) {
		SimpleKMeans clusterer = new SimpleKMeans();
		ImageInfo result = null;

		try {
			clusterer.setNumClusters(numCluster);
			clusterer.setDistanceFunction(new EuclideanDistance());
			result = createClusteredGraphics(clusterer, img, builder);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public static ImageInfo createClusteredGraphics(Clusterer clusterer,
			ImageInfo img, InstanceBuilder builder) {
		analyse(clusterer, img, builder);
		return clustererGraphics(img, clusterer, builder);
	}

	public static void analyse(Clusterer clusterer, ImageInfo img,
			InstanceBuilder builder) {
		Instances instances = buildInstances(img, builder);

		Long begin = System.currentTimeMillis();
		try {
			clusterer.buildClusterer(instances);
		} catch (Exception e) {
			e.printStackTrace();
		}
		Long end = System.currentTimeMillis();

		System.out.println("clustering: " + (end - begin) + "ms");
	}

	public static Instances buildInstances(ImageInfo img,
			InstanceBuilder builder) {
		FastVector attrs = new FastVector();
		for (String str : builder.getAttributs()) {
			attrs.addElement(new Attribute(str));
		}
		Instances instances = new Instances("image", attrs, 0);

		for (int x = 0; x < img.getWidthSquare(); ++x) {
			for (int y = 0; y < img.getHeightSquare(); ++y) {
				Instance inst = builder.createInstance(img, x, y);
				if (inst != null) {
					instances.add(inst);
				}
			}
		}

		return instances;
	}

	public static ImageInfo clustererGraphics(ImageInfo img,
			Clusterer clusterer, InstanceBuilder builder) {

		ImageInfo result = new ImageInfo(img);

		for (int x = 0; x < img.getWidthSquare(); ++x) {
			for (int y = 0; y < img.getHeightSquare(); ++y) {
				int cluster;
				try {
					Instance inst = builder.createInstance(img, x, y);
					if (inst != null) {
						cluster = clusterer.clusterInstance(inst);
						result.setValue(x, y, cluster);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		return result;
	}
}
